package ar.uba.fi.tonyvaliente.signature.query;

import java.util.BitSet;
import java.util.List;

import ar.uba.fi.tonyvaliente.signature.HashFunction;
import ar.uba.fi.tonyvaliente.signature.process.SignatureGenerator;

/**
 * Representa un filtro de signatures por termino.
 * Funciona calculando la signature del termino en cuestion
 * y comparandola con la de un documento para ver si el
 * termino aparece o no en el documento.
 * No descarta falsos positivos.
 * 
 * @author dmorello
 */
public class SignatureTermFilter extends SignatureFilter {
	
	// Termino
	private String term;
	
	/**
	 * Crea una nueva instancia con un termino y un
	 * flag de negacion asociados.
	 * @param term Termino a asociar a la instancia
	 * @param negated flag de negacion
	 * @see SignatureFilter
	 */
	public SignatureTermFilter(String term, boolean negated) {
		super(negated);
		this.term = term;
	}

	@Override
	public boolean eval(BitSet docSignature, List<HashFunction> hashFunctions, int hashLength) throws SignatureQueryException {
		
		// Aplico la mascara a la firma del documento
		BitSet termSignature = SignatureGenerator.calculateWordSignature(term, hashFunctions, hashLength);
		BitSet andSignature = (BitSet)termSignature.clone();
		andSignature.and(docSignature);
		boolean signatureMatch = termSignature.equals(andSignature);
		
		// Devuelvo lo que corresponda segun el flag de negacion
		if (!isNegated()) {
			return signatureMatch;
		} else {
			return !signatureMatch;
		}
	}
	
	/**
	 * Compara dos objetos de esta clase por termino
	 * y flag de negacion
	 * @param f un SignatureTermFilter cualquiera
	 * @return true si son iguales, false si no lo son.
	 */
	public boolean equals(SignatureTermFilter f) {
		return this.isNegated() == f.isNegated() && this.term.equals(f.term);
	}
	
	@Override
	public boolean equals(Object o) {
		if (o == this) return true;
		if (o == null) return false;
		if (!(o instanceof SignatureTermFilter)) return false;
		return equals((SignatureTermFilter)o);
	}
	
	@Override
	public int hashCode() {
		return (isNegated() + term).hashCode();
	}
	
	@Override
	public String toString() {
		if (isNegated()) {
			return "NOT " + term;
		} else {
			return term;
		}
	}
}
